#include "interfaz_fuse.h"


/*____________________________________________________*/

int FS_create(const char *rutaArchivo, mode_t modoApertura, struct fuse_file_info *fi){

	(void)fi;
	int resultado;
	datosArchivo*data=NULL;
	data=malloc(sizeof(datosArchivo));
	data->tipo=ARCHIVO;
	data->tamanioArchivo=0;
	
	char*ruta=malloc(strlen(rutaArchivo)+1);
	
	
		strncpy(ruta,rutaArchivo,strlen(rutaArchivo));
	ruta[strlen(rutaArchivo)]='\0';
	
	resultado=buscarArchivo(ruta,data);
	if(resultado!=0){
		resultado=crearArchivoDirectorio(ruta,data,modoApertura,1);
		data->lista=NULL;

					data->lista=malloc(sizeof(listaClusters));
					data->lista->numCluster=0;
					conseguirCadenaClusters(data->lista,data->numCluster);
		fi->fh= (long)data;
		free(ruta);
return resultado;

	}
	else{
		data->lista=NULL;

				data->lista=malloc(sizeof(listaClusters));
				data->lista->numCluster=0;
				conseguirCadenaClusters(data->lista,data->numCluster);
		fi->fh= (long)data;
		free(ruta);
	}
	return 0;
}

/*____________________________________________________*/

int FS_open(const char *rutaArchivo, struct fuse_file_info *infoArchivo){

	(void)infoArchivo;
	int resultado=0;

	datosArchivo* data=NULL;
	data=malloc(sizeof(datosArchivo));
	char*ruta=malloc(strlen(rutaArchivo)+1);
	
	
		strncpy(ruta,rutaArchivo,strlen(rutaArchivo));
	ruta[strlen(rutaArchivo)]='\0';
	
	resultado=buscarArchivo(ruta,data);
	if(resultado!=0){
		free(ruta);
free(data);
		return (-ENOENT);

	}
else{
data->lista=NULL;

		data->lista=malloc(sizeof(listaClusters));
		data->lista->numCluster=0;
		conseguirCadenaClusters(data->lista,data->numCluster);

	infoArchivo->fh= (long)data;
	free(ruta);
	return 0;
}
}

/*____________________________________________________*/

int FS_read(const char *rutaArchivo, char *buffer, size_t tamanio, off_t offset, struct fuse_file_info* fi){

	datosArchivo* data;
	int resultado;
	data=malloc(sizeof(datosArchivo));
	int inter =(long)(fi->fh);
	data= (datosArchivo*)inter;

	if ((tamanio + (int) offset) > data->tamanioArchivo)
		tamanio = (data->tamanioArchivo - offset);

	resultado=leerDatos(data,buffer,offset,tamanio);
	data->resultadoOper=resultado;
	fi->fh= (long)data;
	buffer[tamanio]='\0';

	if(resultado < 0)
		return resultado;
	else
		return tamanio;
}

/*____________________________________________________*/

int FS_write(const char *rutaArchivo, const char *buffer, size_t tamanio, off_t offset, struct fuse_file_info *fi){
	datosArchivo* data;
	int resultado;
	
	data=malloc(sizeof(datosArchivo));
	data= (datosArchivo*)(long)fi->fh;
	char*ruta=malloc(strlen(rutaArchivo)+1);
	
	
		strncpy(ruta,rutaArchivo,strlen(rutaArchivo));
	ruta[strlen(rutaArchivo)]='\0';
	
		
	resultado=escribirArchivo(ruta,data,buffer,offset,tamanio);
	data->resultadoOper=resultado;
	fi->fh= (long)data;
	if(resultado < 0){
		free(ruta);
			return resultado;
	}
		else{
			free(ruta);
			return tamanio;
		}
}

/*____________________________________________________*/

int FS_flush(const char *rutaArchivo, struct fuse_file_info *fi){
	datosArchivo* data;
	data=malloc(sizeof(datosArchivo));
	data= (datosArchivo*)(long)fi->fh;

	//if(data->resultadoOper<0)
	//	ENOENT; // Levantar proceso manejo de error

	(void) rutaArchivo;
	(void) fi;
	(void)data;
//free(data);
//free((datosArchivo*) ((long)(fi->fh)));

	return 0;
}

/*____________________________________________________*/

int FS_release(const char *ruta, struct fuse_file_info *fi){
    (void) ruta;
    (void) fi;
	free((datosArchivo*) ((long)(fi->fh)));
	return 0;
}

/*____________________________________________________*/

int FS_truncate(const char *rutaArchivo, off_t offset){
	int indice,tamanio;
	float resultado;
	
	datosArchivo* data=NULL;
	data=malloc(sizeof(datosArchivo));
	char*ruta=malloc(strlen(rutaArchivo)+1);
	
	
		strncpy(ruta,rutaArchivo,strlen(rutaArchivo));
	ruta[strlen(rutaArchivo)]='\0';
	
		
		resultado=buscarArchivo(ruta,data);
	if(resultado!=0){
		free(data);free(ruta);
		return resultado;
	}

	/*listaClusters* cadenaClusters=NULL;
	cadenaClusters=malloc(sizeof(listaClusters));
	cadenaClusters->numCluster=0;

	resultado=grabarEntradaArchivo(ruta,offset);
	if(resultado!=0){
		free(data);
		free(cadenaClusters);
		free(ruta);
		return resultado;
	}

	else{

		tamanio=conseguirCadenaClusters(cadenaClusters,data->numCluster);

		if((resultado=(offset/512)/8)>0){

			for(indice=0;indice<resultado;indice++)
				cadenaClusters=cadenaClusters->sig;
			grabar_FAT(cadenaClusters->numCluster,0xFFFFFFF);
			cadenaClusters=cadenaClusters->sig;
			while(cadenaClusters!=NULL){
				grabar_FAT(cadenaClusters->numCluster,0x0000000);
				setSector(cadenaClusters->numCluster,0);
				cadenaClusters=cadenaClusters->sig;
			}
			bajarBitVector();
		}
		free(data);
		free(cadenaClusters);
		free(ruta);

	}*/
if(offset>data->tamanioArchivo){
		char vector[offset-data->tamanioArchivo];
	memset(vector,'\0',offset-data->tamanioArchivo);
		escribirArchivo(ruta,data,vector,data->tamanioArchivo,offset-data->tamanioArchivo);
	return 0;
	}
else{
	char vector[data->tamanioArchivo-offset];
memset(vector,'\0',data->tamanioArchivo-offset);
	escribirArchivo(ruta,data,vector,data->tamanioArchivo,data->tamanioArchivo-offset);
return 0;

}
		return 0;
}

/*____________________________________________________*/

int FS_unlink(const char *path){
	int resultado;
	datosArchivo* data=NULL;
	data=malloc(sizeof(datosArchivo));
	
	listaClusters* cadenaClusters=NULL;
	cadenaClusters=malloc(sizeof(listaClusters));
	cadenaClusters->numCluster=0;
	char*ruta=malloc(strlen(path)+1);
	
	
		strncpy(ruta,path,strlen(path));
	ruta[strlen(path)]='\0';
		resultado=buscarArchivo(ruta,data);
	if(resultado!=0){
		free(ruta);
		return (-ENOENT);
	}
	resultado=borrarEntradaDir(ruta);
	if(resultado==0){
		conseguirCadenaClusters(cadenaClusters,data->numCluster);
		while(cadenaClusters!=NULL){
			grabar_FAT(cadenaClusters->numCluster,0x0000000);
			setSector(cadenaClusters->numCluster,0);
			cadenaClusters=cadenaClusters->sig;
		}
		bajarBitVector();
		free(data);
		free(cadenaClusters);
		free(ruta);
		return 0;

	}
	else{
		free(data);
		free(cadenaClusters);
		free(ruta);
		return resultado;
	}
}

/*____________________________________________________*/

int FS_mkdir(const char *rutaArchivo, mode_t mode){

		int resultado=1;
		datosArchivo* data;
		data=malloc(sizeof(datosArchivo));
		data->tipo=DIRECTORIO;
		data->tamanioArchivo=0;
data->numCluster=0;
			
		char*ruta=malloc(strlen(rutaArchivo)+1);
	
	
		strncpy(ruta,rutaArchivo,strlen(rutaArchivo));
	ruta[strlen(rutaArchivo)]='\0';
		resultado=buscarArchivo(ruta,data);
		if(resultado!=0 ){
			crearArchivoDirectorio(ruta,data,mode,1);
			free(ruta);


			return 0;
		}
		else{free(ruta);
			return (-EEXIST); //el dir ya existe
}
}

/*____________________________________________________*/

int FS_readdir(const char *path, void *buffer, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi){


    	(void) offset;
    	(void) fi;

    	fat32_directory *ptr, *directorio;
   	datosArchivo*data;   
	char*ruta=malloc(strlen(path)+1);
	directorio=malloc(sizeof(fat32_directory));
    	data=malloc(sizeof(datosArchivo));

    	data->tipo=DIRECTORIO;
    	data->tamanioArchivo=0;
	directorio->tipo=0;

    	strcpy(ruta,path);
    	ruta[strlen(path)]='\0';
    	if(strcmp(path,"/")!=0){
    if(buscarArchivo(ruta,data)!=0){
    	free(data);
    	free(ruta);
    	return (-ENOENT);
    }
    	}
    	else
    		data->numCluster=2;

   leerDirectorio(directorio,data->numCluster);
   ptr=directorio;


   filler(buffer, ".", NULL, 0);
   filler(buffer, "..", NULL, 0);

   while (ptr != NULL&&ptr->tipo !=0) {
  
int i;
for(i=0;i<strlen(ptr->nombre)&& (ptr->nombre[i]!=' ');i++);
if(i<strlen(ptr->nombre))
	ptr->nombre[i]='.';
        filler(buffer,ptr->nombre, NULL, 0);


        ptr=ptr->sig;
    }
  
free(data);
    	free(ruta);
   return 0;

	
}

/*____________________________________________________*/

int FS_rmdir(const char *path){
	char buffer[512];
	datosArchivo* data=NULL;
	int resultado;
	data=malloc(sizeof(datosArchivo));
	
	char*ruta=malloc(strlen(path)+1);
	
	
		strncpy(ruta,path,strlen(path));
	ruta[strlen(path)]='\0';
		
		resultado=buscarArchivo(ruta,data);
	if(resultado!=0){
			free(data);
			free(ruta);
			return (-ENOENT);
	}
memset(buffer,0,512);
	leerArchivoDisco(calcularPrimerSectorDelCluster(data->numCluster),buffer);
	
uint8_t i,entrada;
	
	memcpy(&entrada,buffer+64,sizeof(uint8_t));

if((entrada!=0xE5)&&(entrada!=0x00)) //32 para . 32 para ..
		return (-EPERM); //tiene datos dentro
	else{
		listaClusters* cadenaClusters=NULL;
		cadenaClusters=malloc(sizeof(listaClusters));
		cadenaClusters->numCluster=0;
resultado=borrarEntradaDir(ruta);
		if(resultado==0){
			conseguirCadenaClusters(cadenaClusters,data->numCluster);
			while(cadenaClusters!=NULL){
				grabar_FAT(cadenaClusters->numCluster,0x0000000);
				setSector(cadenaClusters->numCluster,0);
				cadenaClusters=cadenaClusters->sig;
			}
			bajarBitVector();
			free(data);
			free(cadenaClusters);
			free(ruta);
			return 0;

		}
		else{
			free(data);
			free(cadenaClusters);
			free(ruta);
			return resultado;
		}
	}
}

/*____________________________________________________*/

int FS_getattr(const char *rutaArchivo, struct stat *statbuffer){

		int resultado = 0;
	datosArchivo* data=malloc(sizeof(datosArchivo));
	char*ruta=malloc(strlen(rutaArchivo)+1);
	memset(statbuffer, 0, sizeof(struct stat));
	
		strncpy(ruta,rutaArchivo,strlen(rutaArchivo));
	ruta[strlen(rutaArchivo)]='\0';
		
if(strcmp(rutaArchivo,"/")==0){
statbuffer->st_mode = S_IFDIR | 0777;
 statbuffer->st_nlink = 2;
return 0;
}

	
else{
if(rutaArchivo[0]=='.')
	return (-ENOENT);
data->numCluster=0;
resultado=buscarArchivo(ruta,data);
	if((resultado)==0) {
if(data->tipo==DIRECTORIO){
	   statbuffer->st_mode = S_IFDIR | 0777;
 statbuffer->st_nlink = 2;
return resultado;

}
else if (data->tipo==ARCHIVO){
 statbuffer->st_mode = S_IFREG | 0777;
	   statbuffer->st_nlink = 1;
	   statbuffer->st_size = data->tamanioArchivo;
	//   statbuffer->st_ino = data->numCluster;
	 //  statbuffer->st_blksize= 512;
	   free(ruta);
	   return resultado;
	  }



}
	else if (resultado==3){
//statbuffer->st_mode = S_IFDIR | 0777;
// statbuffer->st_nlink = 2;
return (-ENOENT);}  else{
	    resultado = (-ENOENT);
	    free(ruta);
	   return resultado;
	  }

}



}

/*____________________________________________________*/

int FS_rename(const char *pathActual, const char *nuevoPath){

	datosArchivo* data=NULL;
	int resultado;
	
	data=malloc(sizeof(datosArchivo));
	if(!strcmp(pathActual,nuevoPath))
		return (-1);
	char*ruta=malloc(strlen(pathActual)+1);
		strncpy(ruta,pathActual,strlen(pathActual));
		ruta[strlen(pathActual)]='\0';
		resultado=buscarArchivo(ruta,data);
	if(resultado!=0){
		free(ruta);
		return resultado;
	}
	else{
		
		char*ruta2=malloc(strlen(nuevoPath)+1);
				strncpy(ruta2,nuevoPath,strlen(nuevoPath));
				ruta2[strlen(nuevoPath)]='\0';
				
		crearArchivoDirectorio(ruta2,data,1,0);
		resultado= borrarEntradaDir(ruta);

		free(ruta);free(ruta2);
		if(resultado!=0)
			return resultado;
		else
			return 0;
	}

}

/*____________________________________________________*/

int FS_fgetattr(const char *rutaArchivo, struct stat *statbuffer){
return  (FS_getattr(rutaArchivo,statbuffer));
}

